package com.itbaizhan.controller;

import com.itbaizhan.service.PaymentService;
import io.github.resilience4j.bulkhead.annotation.Bulkhead;
import io.github.resilience4j.circuitbreaker.annotation.CircuitBreaker;
import io.github.resilience4j.ratelimiter.annotation.RateLimiter;
import io.github.resilience4j.retry.annotation.Retry;
import io.github.resilience4j.timelimiter.annotation.TimeLimiter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
import java.util.function.Supplier;

/**
 * @author spf
 * @date 2024/2/8
 * @time 16:54
 */
@Slf4j
@RestController
@RequestMapping("/order")
public class OrderController {

    @Autowired
    private PaymentService paymentService;

    @GetMapping("/timeout")
    @TimeLimiter(name = "delay", fallbackMethod = "timeoutfallback")
    public CompletableFuture<String> timeout(){
        log.info("********** 进入方法*********");
        // 异步操作
        CompletableFuture<String> stringCompletableFuture = CompletableFuture.supplyAsync((Supplier<String>) () -> (paymentService.timeout()));

        log.info("********** 离开方法 ********");
        return stringCompletableFuture;
    }

    public CompletableFuture<ResponseEntity> timeoutfallback(Exception e){
        e.printStackTrace();
        return CompletableFuture.completedFuture(ResponseEntity.ok("超时了"));
    }

    @GetMapping("/retry")
    @Retry(name = "backendA")
    public CompletableFuture<String> retry(){
        log.info("******** 进入方法 ********");
        CompletableFuture<String> stringCompletableFuture = CompletableFuture.supplyAsync((Supplier<String>) () -> paymentService.index());
        log.info("******** 离开方法 ********");
        return stringCompletableFuture;
    }

    @GetMapping("/circuitbreaker")
    @CircuitBreaker(name = "backendA", fallbackMethod = "fallback")
    public String circuitTest(){
        log.info("******** 进入方法 *******");
        String index = paymentService.index();
        log.info("******** 离开方法 *******");
        return index;
    }

    public String fallback(Exception e){
        e.printStackTrace();
        return "服务繁忙，客官请等待一下！";
    }

    @GetMapping("/slowcircuitbreaker")
    @CircuitBreaker(name = "backendB", fallbackMethod = "slowfallback")
    public String slowCircuitBreakTest(){
        log.info("****** 进入方法 ******");
        String index = paymentService.index();
        log.info("****** 离开方法 ******");
        return index;
    }

    public String slowfallback(Exception e){
        e.printStackTrace();
        return "太慢了";
    }

    @GetMapping("/bulkhead")
    @Bulkhead(name = "backendA", type = Bulkhead.Type.SEMAPHORE)
    public String bulkhead() throws InterruptedException {
        log.info("****** 进入方法 *******");
        TimeUnit.SECONDS.sleep(10);
        String index = paymentService.index();
        log.info("****** 离开方法 *******");
        return index;
    }

    @GetMapping("/threadbulkhead")
    @Bulkhead(name = "backendA", type = Bulkhead.Type.THREADPOOL)
    public CompletableFuture threadBulkHread(){
        log.info("****** 进入方法 ******");
        try {
            TimeUnit.SECONDS.sleep(5);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        log.info("****** 离开方法 ******");
        return CompletableFuture.supplyAsync(() -> "线程池隔离信息。。。。");
    }

    @GetMapping("/limter")
    @RateLimiter(name = "backendA")
    public CompletableFuture limter(){
        log.info("****** 进入方法 ******");
        try {
            TimeUnit.SECONDS.sleep(5);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        log.info("****** 离开方法 ******");
        return CompletableFuture.supplyAsync(() -> "限流");
    }

}
